/*
 *   Copyright 1999-2016 Asiainfo Technologies(China),Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.asiainfo.redis.service.clusterhandler;

import com.asiainfo.redis.entity.ClusterNode;
import com.asiainfo.redis.repository.ClusterNodeRepository;
import com.asiainfo.redis.service.HostService;
import com.asiainfo.redis.service.RedisService;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisClusterNode;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @version v 1.0 on 2016/5/19 16:35
 * @auther william.xu
 */
public class RemoveNode {

    private RedisClusterHandler redisClusterHandler;
    private HostService hostService;
    private ClusterNodeRepository clusterNodeRepository;

    private ClusterNode clusterNode;

    public RemoveNode(RedisClusterHandler redisClusterHandler, HostService hostService, ClusterNodeRepository
            clusterNodeRepository, ClusterNode clusterNode){
        this.redisClusterHandler = redisClusterHandler;
        this.hostService = hostService;
        this.clusterNodeRepository = clusterNodeRepository;
        this.clusterNode = clusterNode;
    }


    public Object doInRedisCluster(RedisClusterConnection connection) throws Exception {
        redisClusterHandler.checkClusterNodes(connection);
        //检查是不是master节点
        RedisClusterNode removeNode = null;
        List<RedisClusterNode> otherMasterNodes = new ArrayList<RedisClusterNode>();
        Iterator<RedisClusterNode> iterator = connection.clusterGetNodes().iterator();
        while (iterator.hasNext()) {
            RedisClusterNode redisClusterNode = iterator.next();
            if (clusterNode.getIp().equals(redisClusterNode.getHost()) && clusterNode.getPort().equals
                    (redisClusterNode.getPort())) {
                removeNode = redisClusterNode;
            } else {
                if (redisClusterNode.getMasterId() == null) {
                    otherMasterNodes.add(redisClusterNode);
                }
            }
        }
        Assert.notNull(removeNode, "集群中找不到该节点");
        if (removeNode.getMasterId() == null) {
            //删除的节点是主节点
            //Map<RedisClusterNode, Collection<RedisClusterNode>> map = redisClusterConnection
            // .clusterGetMasterSlaveMap();
            //if (map.keySet().size() < 3){
            if (otherMasterNodes.size() < RedisService.CLUSTER_MIN_NUM) {
                throw new Exception("当前集群中只有3个主节点，不能再删除主节点了");
            }
            //判断如果存在slot，则不能删除，提示先进行迁移slot
            int[] slots = removeNode.getSlotRange().getSlotsArray();
            if (slots.length > 0) {
                throw new Exception("该节点存在" + slots.length + "个slot的数据，请先把数据迁移到其它节点！");
            }

//                    //开始迁移slot，平均迁移到其它主节点上
//                    int[] slots = removeNode.getSlotRange().getSlotsArray();
//                    int slotsPerNode = slots.length / otherMasterNodes.size();
//                    int index = 0;
//                    for (int i = 0; i < otherMasterNodes.size(); i++){
//                        RedisClusterNode node = otherMasterNodes.get(i);
//                        for (int j = 0; j < slotsPerNode; j++){
//                            migrateSlot(slots[index + j], removeNode, node, redisClusterConnection);
//                        }
//                        index += slotsPerNode;
//                        if (i == (otherMasterNodes.size() - 1)){
//                            for (int j = index; j < slots.length; j++){
//                                migrateSlot(slots[j], removeNode, node, redisClusterConnection);
//                            }
//                        }
//                    }

//                } else {
//                    //删除的节点是从节点
        }
        //Thread.sleep(3000);
        // redis-trib.py中del-node操作先判断如果节点有slot，提示使用reshard操作迁移节点。我这里自动迁移到其它节点上。
        // 现改成不用自动迁移，所以不用等了
        //在集群的其它node上都执行CLUSTER FORGET node_id，执行之前先等待一会，
        // 否则使用以下api执行到最后一个node后报：ERR Can't forget my master!
        //redisClusterConnection.clusterForget(removeNode);
        redisClusterHandler.forgetNode(connection, removeNode);
        //删除表中的node记录
        clusterNodeRepository.delete(clusterNode);
        //删除nodes.conf文件
        hostService.deleteNodesConfigFile(clusterNode);
        return null;

    }
}
